using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using Wizard = Telerik.Charting.Design.Wizard.Wizard;

namespace Telerik.WinControls.UI.Design
{
    public class RadChartComponentEditor : WindowsFormsComponentEditor, IDisposable
    {
        private RadChart radChart;
        private Wizard wizard;
        private ChartDesigner chartDesigner;
        private IDesignerHost dhost;

        public override bool EditComponent(ITypeDescriptorContext context, object component, IWin32Window owner)
        {
            IComponent c = component as IComponent;
            if (c != null)
            {
                IServiceProvider provider = c.Site;
                this.dhost = (IDesignerHost) provider.GetService(typeof (IDesignerHost));
            }

            this.chartDesigner = (ChartDesigner) dhost.GetDesigner(c);

            this.radChart = component as RadChart;
            if (radChart == null)
            {
                throw new ArgumentException("Component must be a RadChart object", "component");
            }

            bool changed = false;

            try
            {
                wizard = new Wizard(this.chartDesigner);

                wizard.GetDataSourcesList = GetDataSourcesList;
                wizard.GetSelectedDataSourceName = GetSelectedDataSourceName;
                wizard.GetData = GetData;
                wizard.DataSourceChanged = DataSourceChanged;
                wizard.SetDataSourceID = SetDataSource;
                wizard.btn_Data_Edit.Visible = false;

                Form form = new Form();
                form.ControlAdded += new ControlEventHandler(form_ControlAdded);
                form.Region = wizard.Region;
                form.Name = "RadChartComponentEditorForm";
                form.StartPosition = FormStartPosition.CenterScreen;
                form.Text = " r.a.d.chart Wizard";
                form.AccessibleRole = AccessibleRole.None;
                form.AutoScaleDimensions = new SizeF(6F, 13F);
                form.AutoScaleMode = AutoScaleMode.Font;
				form.ClientSize = new Size(wizard.Size.Width, wizard.Size.Height + 10);
                form.FormBorderStyle = FormBorderStyle.None;
                form.ShowIcon = false;

                form.Controls.Add(wizard);

                if (form.ShowDialog(owner) == DialogResult.OK)
                {
                    changed = true;
                }
            }
            catch
            {
                changed = false;
            }
            return changed;
        }

        private void form_ControlAdded(object sender, ControlEventArgs e)
        {
            wizard.WizardAdded((Form) sender);
        }

        private List<String> GetDataSourcesList()
        {
            List<String> rList = new List<string>();
            foreach (Object comp in radChart.Site.Container.Components)
            {
                if (comp is IList || comp is IBindingList || comp is IListSource)
                {
                    rList.Add(TypeDescriptor.GetProperties(comp)["Name"].GetValue(comp).ToString());
                }
            }
            return rList;
        }

        /// <summary>
        /// Method returns property descriptor by property name.
        /// </summary>
        /// <param name="propName">Property name</param>
        /// <returns>Property descriptor</returns>
        private PropertyDescriptor GetPropertyByName(string propName)
        {
            PropertyDescriptor prop = TypeDescriptor.GetProperties(radChart)[propName];
            if (null == prop)
            {
                throw new ArgumentException("Matching property not found.", propName);
            }
            else
            {
                return prop;
            }
        }

        private void SetDataSource()
        {
            try
            {
                GetPropertyByName("DataSource").SetValue(radChart, ((RadChart) wizard.ChartControlWorking).DataSource);
            }
            catch
            {
                radChart.DataSource = ((RadChart) wizard.ChartControlWorking).DataSource;
            }
			radChart.DataManager.UseAutoBind = false;
            chartDesigner.Update();
        }

        private static string GetDataSourceName(object dataSource)
        {
            string _name = string.Empty;

            if (dataSource != null)
            {
                IComponent ds = dataSource as IComponent;

                if (ds != null)
                {
                    if (ds.Site != null)
                    {
                        _name = ds.Site.Name;
                    }
                    else
                    {
                        _name = dataSource.GetType().Name;
                    }
                }
                else
                {
                    _name = dataSource.GetType().Name;
                }
            }

            return _name;
        }

        private String GetSelectedDataSourceName()
        {
            return GetDataSourceName(((RadChart) wizard.ChartControlWorking).DataSource);
        }

        private void GetData()
        {
            object data = wizard.ChartControlWorking.Chart.DataManager.DataSource;
            if (data != null)
            {
                wizard.DataSourceViewSelectCallback(data);
            }
        }

        private void DataSourceChanged(object sender, EventArgs e)
        {
            radChart.DataManager.UseAutoBind = true;

            ComboBox cbDataSource = sender as ComboBox;
            if (cbDataSource != null)
            {
                if (cbDataSource.SelectedIndex == cbDataSource.Items.Count - 1)
                {
                    chartDesigner.AddNewDataSource();
                }
                else if (cbDataSource.SelectedIndex == 0)
                {
                    ((RadChart) wizard.ChartControlWorking).DataSource = null;
                }
                else
                {
                    ((RadChart) wizard.ChartControlWorking).DataSource = chartDesigner.FindDataSource(cbDataSource.SelectedItem.ToString());
                }
            }

            chartDesigner.Update();
        }

        #region IDisposable Members

        ~RadChartComponentEditor()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                wizard.Dispose();
            }
        }

        #endregion
    }
}